init = function(){}

var controller   = require('../server/RemotingController'),
	remote       = require('../Remoting.js').create(),
	CommandChain = require('../CommandChain.js'),
    app          = require('express').createServer();

var rawBodyParser = function(req, options, callback){
	var _parser = require('connect').bodyParser();
	req.rawBody = '';
	req.on('data', function(chunk){
		req.rawBody += chunk;
	});
	_parser(req, options, callback);
};

exports.Remoting = {
	setUp : function(onDone){
		controller.set('service1',{
			getChild : function(){
				return { 
					msg:'Child'
				}
			}
			,property1 : "Property1"
			,__serviceName : 'service1'
		});
		controller.set('service2',{
			createService1 : function(){
				return controller.get('service1');
			}
			,property2 : "Property2"
		});
		controller.set('service3',{
			callback : function(doCallback, onYes, onNo){
				if(doCallback) 
					onYes();
				else 
					onNo();
			}
			,property3 : "Property3"
		});

		app.use(rawBodyParser);
		app.listen(8080);

		controller.register(app);
		onDone();
	},
	tearDown : function(onDone){
		app.close();
		onDone();
	},
	
	testRemoteCallback : function(assert){
		var onFail = function(){
			assert.ok(false, 'Incorrect callback method invoked.');
			assert.done();
		};
		//Create a remote service
		var svc = remote.createRemoteService('service3');
		assert.ok(svc);
		svc.on('ready', function(){
			assert.ok(svc.callback);
			assert.equal(svc.property3, "Property3");
			var chain = CommandChain.create();
			var onPass = function(){
				chain.proceed();
			};
			if(svc.callback){
				chain.invoke(svc.callback, [true, onPass, onFail], svc);
				chain.invoke(svc.callback, [false, onFail, onPass], svc);
				chain.execute(function(){
					assert.done();
				});
			}else{
				assert.done();
			}
		});
		svc.on('error', onFail);
	},
	/**
	 * testRemoteReference -
	 *  ensure that a remote reference will automatically construct
	 *  another remote reference.
	 *  
	 */
	testRemoteReference : function(assert){
		var failTest = function(err){
			assert.ok(false, 'Failed to connect');
			assert.done();
		};
		//Ensures a remote reference is usable
		var verifyEndpoint = function(result){
			assert.ok(result);
			assert.equal(result.msg, 'Child');
			assert.done();
		};
		//Ensures a remote reference is initialized
		var verifyRemoteEndpoint = function(result){
			assert.ok(result);
			assert.ok(result.getChild)
			assert.equal(result.property1, "Property1");
			if(result.getChild){
				var child = result.getChild();
				child.on('ready', verifyEndpoint);
				child.on('error', failTest);
			}else{
				failTest('getChild method not available');
			}
		};
		
		//Create a remote service
		var svc = remote.createRemoteService('service2');
		assert.ok(svc);
		svc.on('ready', function(){
			assert.ok(svc.createService1);
			assert.equal(svc.property2, "Property2");
			//Construct remote reference from remote service
			var svc1 = svc.createService1();
			svc1.on('ready', verifyRemoteEndpoint);
			svc1.on('error', failTest);
		});
		svc.on('error', failTest);
	},
	/**
	 * testCreateRemoteService -
	 *  Ensure we can create a remote service
	 *  
	 */
	testCreateRemoteService : function(assert){
		var svc = remote.createRemoteService('service1');
		assert.ok(svc);
		var failTest = function(err){
			assert.ok(false, 'Failed to connect');
			assert.done();
		};
		var verifyEndpoint = function(result){
			assert.ok(result);
			assert.equal(result.msg, 'Child');
			assert.done();
		};
		svc.on('ready', function(){
			assert.equal(svc.property1, "Property1");
			assert.ok(svc.getChild);
			var child = svc.getChild();
			child.on('ready', verifyEndpoint);
			child.on('error', failTest);
		});
		svc.on('error', failTest);
	}
}